package com.sensePlusVR.realGame;

//import java.util.Timer;
//import java.util.TimerTask;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.videolan.libvlc.IVLCVout;
import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.Media;
import org.videolan.libvlc.MediaPlayer;
import org.videolan.libvlc.MediaPlayer.Event;

import android.content.Context;
import android.graphics.SurfaceTexture;
import android.util.Log;

import com.sensePlusVR.utils.MyLog;
//import android.os.Handler;

public class VideoGamePlayer {
	public static final String TAG="VideoGamePlayer";
	public static final int PLAY_MODE_START = 0;
	public static final int PLAY_MODE_END = 1;
	
	public static final int PLAY_ACTION = 2;
	public static final int PLAY_NEXT_ACTION = 3;
	public static final int PLAY_VIDEO  = 4;
	public static final int PLAY_NEXT_VIDEO = 5;
	public static final int PLAY_NEXT_GAME = 6;

	public static final int GAME_EVENT_PLAY_ACTION = 0;
	public static final int GAME_EVENT_PLAY_VIDEO  = 1;
	public static final int GAME_EVENT_FINISHED    = 2;
	public static final int GAME_EVENT_SPEED_FPS = 3;
	public static final int GAME_EVENT_ERROR = 4;
	public static final int GAME_EVENT_VIDEO_WILL_END = 5;
	//public static final int GAME_EVENT_PLAY_ACTION = 0;
	
	private final float mBackAudioV = 0.2f;
	public final float mWomanAudioV = 0.8f;
	private final int TIME_REMAIN = 2000;
	private LibVLC      mVlc1;
	private MediaPlayer mActionPlayer;
	private LibVLC      mVlc2;
	private MediaPlayer mVideoPlayer;
	
	private RealGameControllerV2 mVideoGame;
	//private int play_mode;
	private SurfaceTexture  nativeTexture;
	private SurfaceTexture  nativeBlendTexture;
	//private int mSpeed = 0;
	//private int mActionDir = 0;
	
	private AudioPlayer mBackAudio;
	private AudioPlayer mWomanAudio;
	//private SoundPlayer mSoundPlayer;
	private PlayFade   mFadePlayer;
	//private AudioManager mAudioManager;
	//private String mCurrentSound;
	private boolean mStarting = false;
	private Context mContext;
	private int mSpeedLevel = -1;
	//private int mPrevSpeedLevel = -1;
	private boolean mNeedPlayWhenStop = false;
	private boolean mVideoPlayerPauseed = false;
	private boolean mAudioPlayerPauseed = false;
	private boolean mActionPlayerPaused = false;
	private Lock    mGameLock;
	private Lock    mAudioLock;
	private String  mVlcCodecOptions;
	//private CpuInfo mCpuInfo;
	private boolean mTestMode;
	private String mTestActions;
	private final long AUDIO_LOW_INTERVAL = 500;
	private final long AUDIO_FAST_INTERVAL = 250;
	private long mNextAudioPlayTime;
	private long mAudioIntervalTime;
	private float mAlpha = 1.0f;
	private AudioPlayer.EventListener al = new AudioPlayer.EventListener() {
		
		@Override
		public void onEvent(int event, Object args) {
			// TODO Auto-generated method stub
			Log.e(TAG, "audio stoped..");
			checkIdleAudio();
		}
	};
	
	private void setNextPlayAudioTime(){
		mNextAudioPlayTime = System.currentTimeMillis() + mWomanAudio.getDuration() + mAudioIntervalTime;
	}
	
	private boolean canPlayAudioNow(){
		if (System.currentTimeMillis() >= mNextAudioPlayTime)
			return true;
		return false;
	}
	
	public VideoGamePlayer(Context context){
		//play_mode = PLAY_MODE_START;
		mTestMode = false;
		mAudioIntervalTime = AUDIO_LOW_INTERVAL;
		//mCpuInfo = VRApplication.getInstance().getCPUInfo();
		mContext = context;
		mGameLock = new ReentrantLock();
		mAudioLock = new ReentrantLock();
		//mHandler = new Handler( );
		mBackAudio = new AudioPlayer(mBackAudioV);
		mWomanAudio = new AudioPlayer(mWomanAudioV);
		mWomanAudio.setOnEventListener(al);
		//mSoundPlayer = new SoundPlayer();
		mFadePlayer = new PlayFade();
		//mAudioManager = Context.
		mFadePlayer.start();
	}
	
	public VideoGamePlayer(Context context, String action){
		mTestMode = true;
		mGameLock = new ReentrantLock();
		mContext = context;
		mTestActions = action;
		mVlcCodecOptions = MediaPlayer.HardwareDecoder;
		createActionPlayer();
	}
	
	public void releaseActionPlay(){
		mGameLock.lock();
		if (mActionPlayer != null && !mActionPlayer.isReleased()){
			if (mActionPlayer.isGamePlaying()){
				Log.e(TAG, "stop action");
				mActionPlayer.stopGame();
				Log.e(TAG, "stop action ok");
			}
			setActionPlayerSurface(null);
			Log.e(TAG, "release action..");
			mActionPlayer.releaseSync();
			//wait(500);
			Log.e(TAG, "release action ok");
		}
		mActionPlayer = null;
		Log.e(TAG, "relase action vlc");
		if (mVlc1 != null && !mVlc1.isReleased())
			mVlc1.release();
		Log.e(TAG, "relase action vlc ok");
		mVlc1 = null;
		mGameLock.unlock();
	}

	public void releaseVideoPlay(){
		mGameLock.lock();
		if (mVideoPlayer != null && !mVideoPlayer.isReleased()){
			Log.e(TAG, "stop videoplayer");
			if (mVideoPlayer.isPlaying() || mVideoPlayerPauseed){
				mVideoPlayer.stopSync();
				Log.e(TAG, "stop videoplayer...");
			}
			Log.e(TAG, "stop videoplayer ok");
			setVideoPlayerSurface(null);
			mVideoPlayer.releaseSync();
			//wait(500);
			Log.e(TAG, "stop video release");
		}
		mVideoPlayer = null;
		Log.e(TAG, "relase videoplayer vlc");
		if (mVlc2 != null && !mVlc2.isReleased())
			mVlc2.release();
		Log.e(TAG, "relase videoplayer vlc ok");
		mVlc2 = null;
		mGameLock.unlock();
	}
	
	public void release(){
		releaseActionPlay();
		releaseVideoPlay();
		audioStop();
		audioRelease();
	}
	
	private void audioStop(){
		mAudioLock.lock();
		mAudioPlayerPauseed = true;
		mBackAudio.stop();
		mWomanAudio.stop();
		mAudioLock.unlock();
	}
	
	
	private void audioRelease(){
		Log.e(TAG, "release audio");
		mAudioLock.lock();
		mAudioPlayerPauseed = true;
		mBackAudio.release();
		mWomanAudio.release();
		mAudioLock.unlock();
		Log.e(TAG, "release audio ok");
	}	
	
	public void stopWomanAudio(){
		mAudioLock.lock();
		mAudioPlayerPauseed = true;
		if (mWomanAudio.isPlaying())
			mWomanAudio.stop();
		mAudioLock.unlock();
	}
	
	public  void startWomanAudio(){
		mGameLock.lock();
		String audio = mVideoGame.getSound(AudioLevel.IDLE);
		mGameLock.unlock();
		mAudioLock.lock();
		if (!mWomanAudio.isPlaying()) {
			mWomanAudio.play(audio);
			setNextPlayAudioTime();
		}
		mAudioPlayerPauseed = false;
		mAudioLock.unlock();
	}
	
	private void createVideoPlayer(){
		mGameLock.lock();
		if (mVideoPlayer == null){
			mVlc2 = new LibVLC();
			mVlc2.cacheActivity(mContext);
			mVideoPlayer = new MediaPlayer(mVlc2);
		}
		mGameLock.unlock();
	}
	
	
	public void createActionPlayer(){
		mGameLock.lock();
		if (mActionPlayer == null){
			mVlc1 = new LibVLC();
			mVlc1.cacheActivity(mContext);
			mActionPlayer = new MediaPlayer(mVlc1);
			mActionPlayer.gameInit(mVlcCodecOptions);
		}
		mGameLock.unlock();
	}
	
	private void getVlcCodecOptions(){
/*		String videoRes = null;
		if (mCpuInfo != null && !mCpuInfo.getCpucode().equals("unknow")){
			videoRes = mCpuInfo.getHwdecoder();
		}else{
			videoRes = "unknow";
		}
		if (mCpuInfo != null)
			Log.e(TAG, "cpuInfo="+mCpuInfo.toString());
		VideoResolution.videoResolution vres = VideoResolution.getVideoResolution(videoRes);
		if (vres == null){
			mVlcCodecOptions = null;//MediaPlayer.HardwareDecoder;
			return;
		}
		int w = mVideoGame.getActionVideoWidth();
		int h = mVideoGame.getActionVideoHeight();
		if (w * h > vres.getWidth() * vres.getHeight()){
			mVlcCodecOptions = MediaPlayer.softwareDecoder;
		}else{
			mVlcCodecOptions = MediaPlayer.HardwareDecoder;
		}*/
		
		mVlcCodecOptions = MediaPlayer.HardwareDecoder;
	}
	
	public void create(String configfile){
		mGameLock.lock();
		mVideoGame = new RealGameControllerV2(configfile);
		getVlcCodecOptions();
		mGameLock.unlock();
		createVideoPlayer();
		createActionPlayer();
		//setSoundPool();
		//mPrevSpeedLevel = -1;
		mSpeedLevel = AudioLevel.IDLE;
		mNeedPlayWhenStop = false;
		mVideoPlayerPauseed = false;
		mAudioPlayerPauseed = false;
		mActionPlayerPaused = false;
	}
	
	public int getSourceType()
	{
		if (mVideoGame != null)
			return mVideoGame.getSourceType();
		return 0;
	}
	
	public int getConfigVersion()
	{
		if (mVideoGame != null)
			return mVideoGame.getConfigVersion();
		return 0;
	}

	
//	private void checkPlayNeeded(){
//		mGameLock.lock();
//		String audio = mVideoGame.getSound(mSpeedLevel);
//		mGameLock.unlock();
//		
//		mAudioLock.lock();
//		Log.e(TAG, "checkPlayNeeded...");
//		if (!mAudioPlayerPauseed && !mWomanAudio.isPlaying()){
//			mFadePlayer.play(audio);
//		}
//
//		mAudioLock.unlock();
//	}
	private String getAudioFile(int level){
		mGameLock.lock();
		String audio = mVideoGame.getSound(level);
		mGameLock.unlock();	
		return audio;
	}
	private void checkIdleAudio(){
		String audio = null;
		mAudioLock.lock();
		if (mSpeedLevel == AudioLevel.IDLE){
			if (!mAudioPlayerPauseed) {
				audio = getAudioFile(AudioLevel.IDLE);
				mFadePlayer.play(audio);
			}
		}else if (mNeedPlayWhenStop){
			if (!mAudioPlayerPauseed && canPlayAudioNow()){
				audio = mVideoGame.getSound(mSpeedLevel);
				mFadePlayer.play(audio);
			}
			mNeedPlayWhenStop = false;
		}
		mAudioLock.unlock();
	}
	
	private void PlaySound2(int speed){
		mGameLock.lock();
		int step = mVideoGame.getStep(speed);
		mGameLock.unlock();
		if (mVideoGame.getConfigVersion() >= 3)
			step = speed;
		mAudioLock.lock();
		if (step == AudioLevel.LOW){
			mAudioIntervalTime = AUDIO_LOW_INTERVAL;
		}else if (step == AudioLevel.MID){
			mAudioIntervalTime = AUDIO_FAST_INTERVAL;
		} 
		Log.e(TAG, "mSpeedLevel="+mSpeedLevel+", step="+step);
		if ((step == mSpeedLevel) ) {
			if (mWomanAudio.isPlaying()) {
				mNeedPlayWhenStop = true;
				mAudioLock.unlock();
				return;
			}
			if (!canPlayAudioNow()){
				mAudioLock.unlock();
				return;
			}
		}
		mSpeedLevel = step;
		mNeedPlayWhenStop = false;
		if (!mAudioPlayerPauseed) {
			String audio = getAudioFile(mSpeedLevel);
			mFadePlayer.play(audio);
		}
		mAudioLock.unlock();
	}	

	public void pauseAudio(){
		//mBackAudio.pause();
	}
	
	public void PlayTest(){
		PlayAction();
	}
	
	public void PlayTestStop(){
		stopActionPlay();
	}
	
	public void Play(){
		mGameLock.lock();
		String back = mVideoGame.getBackAudioFile();
		mGameLock.unlock();
		mBackAudio.play(back, true);	
		PlayStartVideo();
	}
	
	public float showActionFrame(){
		float alpha = -1.0f;
		mGameLock.lock();
		if (mActionPlayer != null && !mActionPlayer.isReleased() && mActionPlayer.isGamePlaying()){
			int frames = mActionPlayer.updateFrame();
			if (frames== 2) {
				alpha = mActionPlayer.getBlendAlpha();
				mAlpha = alpha;
			}
			else if (frames == 1){
				alpha = 1.0f;
				mAlpha = alpha;
			}
		}else if (mAlpha != 1.0f){
			alpha = mAlpha = 1.0f;
		}
		mGameLock.unlock();
		
		return alpha;
	}
	
	public void setPlayerSurface(SurfaceTexture surface){
		nativeTexture = surface;
	}
	
	public void setBlendSurface(SurfaceTexture surface){
		nativeBlendTexture = surface;
	}
	
	private void setVideoPlayerSurface(SurfaceTexture surface){
		IVLCVout vout = mVideoPlayer.getVLCVout();
		if (surface != null){
			if (!vout.areViewsAttached()) {
				vout.setVideoSurface(surface);
				vout.attachViews();
			}
		}else {
			if (vout.areViewsAttached()){
				vout.detachViews();
			}
		}
	}
	
	public void setDepth(float depth){
		mGameLock.lock();
		if (mActionPlayer != null && !mActionPlayer.isReleased() && mActionPlayer.isGamePlaying())
			mActionPlayer.DisplayIndex(depth);
		mGameLock.unlock();
	}
	
	private void setActionPlayerSurface(SurfaceTexture surface){
		IVLCVout vout = mActionPlayer.getVLCVout();
		if (surface != null){
			if (!vout.areViewsAttached()) {
				if (nativeBlendTexture != null){
					Log.e(TAG, "setBlendVideoSurface");
					vout.setBlendVideoSurface(nativeBlendTexture);
				}
				vout.setVideoSurface(surface);
				vout.attachViews();
			}
		}else {
			if (vout.areViewsAttached()){
				vout.detachViews();
			}
		}
	}
	
	public void PlayAction(){
		Log.e(TAG, "PlayAction");
		mGameLock.lock();
		if (mActionPlayer == null)
			createActionPlayer();
		setActionPlayerSurface(nativeTexture);
		String action = null;
		if (mTestMode){
			action = mTestActions;
		}else{
			action = mVideoGame.getCurrentAction();
		}
		
		Log.e(TAG, "current action:"+action);
		mActionPlayer.SetGameAction(action);
		mActionPlayer.setEventListener(gameListener);
		mActionPlayer.playGame(0);
		mGameLock.unlock();
		Log.e(TAG, "PlayAction end");
	}
	
	public void changePlayMinor(){
		mGameLock.lock();
		if (mActionPlayer != null){
			mActionPlayer.changeMinor(-1);
		}
		mGameLock.unlock();
	}
	
	public void LastAction(){
		mGameLock.lock();
		mVideoGame.LastAction();
		mGameLock.unlock();		
	}
	
	public boolean CurrentActionIsVideo(){
		if (mVideoGame.getCurrentAction() == null)
			return true;
		else
			return false;
	}
	
	public void PlayNextAction(){
		mGameLock.lock();
		mVideoGame.NextAction();
		mGameLock.unlock();
		PlayAction();
	}
	
	public void NextAction(){
		mGameLock.lock();
		mVideoGame.NextAction();
		mGameLock.unlock();
		mAudioLock.lock();
		mWomanAudio.stopFade(1000.0f);
		mAudioLock.unlock();
	}
	
	public void PlayDesVideo()
	{
		mGameLock.lock();
		setVideoPlayerSurface(nativeTexture);
		String video = mVideoGame.getCurrentDesVideo();
		Media media = new Media(mVlc2, video);
		media.setHWDecoderEnabled(true, true);
		mVideoPlayer.setMedia(media);
		mVideoPlayer.setEventListener(startVideoListener);
		mStarting = true;
		mVideoPlayer.play();
		mGameLock.unlock();
	}
	
	public void PlayNextDesVideo()
	{
		mGameLock.lock();
		mVideoGame.NextAction();
		mGameLock.unlock();
		PlayDesVideo();
	}
	
	public void PlayStartVideo(){
		mGameLock.lock();
		setVideoPlayerSurface(nativeTexture);
		String video = mVideoGame.getStartVideo();
		Media media = new Media(mVlc2, video);
		media.setHWDecoderEnabled(true, true);
		mVideoPlayer.setMedia(media);
		mVideoPlayer.setEventListener(startVideoListener);
		mStarting = true;
		mVideoPlayer.play();
		mGameLock.unlock();
	}
	
	public void PlayEndVideo(){
		mGameLock.lock();
		setVideoPlayerSurface(nativeTexture);
		String video = mVideoGame.getEndVideo();
		Media media = new Media(mVlc2, video);
		media.setHWDecoderEnabled(true, true);
		mVideoPlayer.setMedia(media);
		mVideoPlayer.setEventListener(endVideoListener);
		mStarting = true;
		mVideoPlayer.play();
		mGameLock.unlock();
		
	}

	public boolean supportVideoMode(){
		if (mVideoGame.getConfigVersion() > 3)
			return true;
		return mVideoGame.supportVideo();
	}
	
	public void stopVideoPlay(){
		Log.e(TAG, "stopVideoPlay");
		mGameLock.lock();
		if (mVideoPlayer != null && mVideoPlayer.isPlaying()) {
			mVideoPlayer.stopSync();
		}
		mGameLock.unlock();
		Log.e(TAG, "stopVideoPlay end");
	}
	
	public void stopActionPlay(){
		Log.e(TAG, "stopActionPlay");
		mGameLock.lock();
		if (mActionPlayer != null && mActionPlayer.isGamePlaying()) {
			mActionPlayer.stopGame();
		}
		mGameLock.unlock();
		Log.e(TAG, "stopActionPlay end");
	}
	
	private final MediaPlayer.EventListener startVideoListener = new MediaPlayer.EventListener(){

		@Override
		public void onEvent(Event event) {
			// TODO Auto-generated method stub
			switch (event.type) {
			case MediaPlayer.Event.Playing:
				Log.e(TAG, "start playing");
				break;
			case MediaPlayer.Event.EndReached:
				Log.e(TAG, "play end");
				break;
			case MediaPlayer.Event.PositionChanged:
				//Log.e(TAG, "postion="+event.getPositionChanged());
				break;
			case MediaPlayer.Event.TimeChanged:
				//Log.e(TAG, "time="+event.getTimeChanged());
				//Log.e(TAG, "Durtion="+mVideoPlayer.getMedia().getDuration());
				long duration = mVideoPlayer.getMedia().getDuration();
				long time = event.getTimeChanged();
				if ((duration - time < TIME_REMAIN) && lEvent != null ){
					if (lEvent != null)
					{
						Log.e(TAG,"time to change video!");
						if (getConfigVersion() != 1 && mStarting)
							lEvent.onEvent(GAME_EVENT_VIDEO_WILL_END, 3, 1);
						else if (mStarting)
							lEvent.onEvent(GAME_EVENT_PLAY_VIDEO, 3, 1);
					}
					mStarting = false;
				}
					
				break;
			case MediaPlayer.Event.Stopped:
				Log.e(TAG, "s play stoped");
				//setVideoPlayerSurface(null);
				//mVideoPlayer.release();
				//mVideoPlayer = new MediaPlayer(mVlc2);
				//PlayEndVideo();
				break;
			case MediaPlayer.Event.EncounteredError:
				MyLog.e(TAG, "video player is Error");
				lEvent.onEvent(GAME_EVENT_ERROR, 0, 0);
				break;	
			}
		}
		
	};
	private final MediaPlayer.EventListener endVideoListener = new MediaPlayer.EventListener(){

		@Override
		public void onEvent(Event event) {
			// TODO Auto-generated method stub
			switch (event.type) {
			case MediaPlayer.Event.Playing:
				Log.e(TAG, "start playing");
				break;
			case MediaPlayer.Event.EndReached:
				Log.e(TAG, "env video play end");
				if (lEvent != null && getConfigVersion() < 3)
					lEvent.onEvent(GAME_EVENT_FINISHED, 0, 0);
				break;
			case MediaPlayer.Event.PositionChanged:
				//Log.e(TAG, "postion="+event.getPositionChanged());
				break;
			case MediaPlayer.Event.TimeChanged:
				long duration = mVideoPlayer.getMedia().getDuration();
				long time = event.getTimeChanged();
				if ((duration - time < TIME_REMAIN) && lEvent != null ){
					if (lEvent != null)
					{
						Log.e(TAG,"time to change video!");
						if (getConfigVersion() != 1 && mStarting)
							lEvent.onEvent(GAME_EVENT_VIDEO_WILL_END, 3, 1);
						else if (mStarting)
							lEvent.onEvent(GAME_EVENT_PLAY_VIDEO, 3, 1);
					}
					mStarting = false;
				}				
				break;
			case MediaPlayer.Event.Stopped:
				Log.e(TAG, "e play stoped");
				//setVideoPlayerSurface(null);
				//mVideoPlayer.release();
				//mVideoPlayer = new MediaPlayer(mVlc2);
				//PlayEndVideo();
				break;
			case MediaPlayer.Event.EncounteredError:
				MyLog.e(TAG, "end player is Error");
				lEvent.onEvent(GAME_EVENT_ERROR, 0, 0);
				break;
			}
		}
		
	};
	
	private final MediaPlayer.EventListener gameListener = new MediaPlayer.EventListener(){

		@Override
		public void onEvent(Event event) {
			// TODO Auto-generated method stub
			switch (event.type) {
			case MediaPlayer.Event.ChangeSpeed:
				if (mTestMode){
					lEvent.onEvent(GAME_EVENT_SPEED_FPS, event.getGameSpeed(), 0);
					break;
				}
				int mSpeed = (event.getGameSpeed() & 0xffff0000) >> 16;
				int mActionDir = (event.getGameSpeed() & 0xffff) ;
				Log.e(TAG, "speed="+mSpeed);
				Log.e(TAG, "actionDir="+mActionDir);
				if (mSpeed == 0){
					PlaySound2(mSpeed);
				}else if (mActionDir == 1){//down to play
					PlaySound2(mSpeed);
				}
				break;
			case MediaPlayer.Event.ChangeAction:
				if (mTestMode)
					break;
				Log.e(TAG, "action main="+event.getGameActionMain()+" ,minor="+event.getGameActionMinor());
				mGameLock.lock();
				mVideoGame.setCurrentMinor(event.getGameActionMinor());
				mGameLock.unlock();
				break;
			case MediaPlayer.Event.EncounteredError:
				MyLog.e(TAG, "Game player is Error");
				lEvent.onEvent(GAME_EVENT_ERROR, 0, 0);
				break;
			case MediaPlayer.Event.EndReached:
				lEvent.onEvent(GAME_EVENT_FINISHED, 0, 0);
				break;
			}
		}
		
	};
	public void pause(){
		mAudioLock.lock();
		mAudioPlayerPauseed = true;
		mBackAudio.pause();
		mWomanAudio.pause();
		mAudioLock.unlock();
		mGameLock.lock();
		if (mVideoPlayer.isPlaying()){
			mVideoPlayer.pause();
			mVideoPlayerPauseed = true;
		}
		
		if (mActionPlayer !=null && mActionPlayer.isGamePlaying()){
			mActionPlayerPaused = true;
		}
		mGameLock.unlock();
		stopActionPlay();
	}
	
	public void resume(){
		mGameLock.lock();
		if (mVideoPlayerPauseed){
			mVideoPlayer.play();
			mVideoPlayerPauseed = false;
		}
		mGameLock.unlock();
		if (mActionPlayerPaused){
			PlayAction();
			mActionPlayerPaused = false;
		}
		mAudioLock.lock();
		if (mAudioPlayerPauseed){
			mBackAudio.resume();
			String audio = mVideoGame.getSound(AudioLevel.IDLE);
			mFadePlayer.play(audio);
			mAudioPlayerPauseed = false;
		}
		mAudioLock.unlock();
	}
	
	private void playAudioMayFade(Command c){
		mAudioLock.lock();
		if (mAudioPlayerPauseed){
			Log.e(TAG, "mAudioPlayerPauseed");
			mAudioLock.unlock();
			return;
		}
		if (!mWomanAudio.isPlaying()){
			Log.e(TAG, "mAudioPlayer play audio");
			mWomanAudio.play(c.audio);
			setNextPlayAudioTime();
			mAudioLock.unlock();
		}else {
			int remain = mWomanAudio.getRemain();
			int getDuration = mWomanAudio.getDuration();
			mAudioLock.unlock();
			float radio = ((float) remain)/((float)getDuration);
			Log.e(TAG, "radio="+radio);
			if (radio > 0.4f){
				//return;
			}
			int fadeTime = 200;//ms
			int delay = 30;
			boolean needFade = false;
			if (remain >= fadeTime){
				needFade = true;
				if (remain > 400)
					fadeTime = 400;
			}
			Log.e(TAG, "FADE............remain="+remain+", fadeTime="+fadeTime);
			float step = mWomanAudioV / (fadeTime/delay);
			float currV = mWomanAudioV - step;
			while(needFade && currV >= 0.0f){
				mAudioLock.lock();
				mWomanAudio.setVolume(currV);
				mAudioLock.unlock();
				currV = currV - step;
				delay(delay);
			}
			mAudioLock.lock();
			//mWomanAudio.stop();
			if (!mAudioPlayerPauseed) {
				mWomanAudio.play(c.audio);
				setNextPlayAudioTime();
			}
			mAudioLock.unlock();
		}		
	}
	

	
	private GameEvent lEvent;
	public void setGameEventListener(GameEvent event){
		lEvent = event;
	}
	public interface GameEvent{
		void onEvent(int event, int arg0, int arg1);
	};
	
	public void delay(int ms){
		try {
			Thread.sleep(ms);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public class Command{
		public static final int COMMAND_START = 0;
		public static final int COMMAND_RELEASE = 0;
		public int command;
		public boolean loop;
		public String audio;
		
		public Command(int command,  boolean loop, String audio){
			this.command = command;
			this.loop = loop;
			this.audio = audio;
		}
	}
	
	public class PlayFade extends Thread{
		private boolean b_exits;
		//private boolean b_isPlaying;
		//private Lock lock = new ReentrantLock();
		private BlockingQueue<Command> cmdQueue = new LinkedBlockingQueue<Command>();
		public PlayFade(){
			//this.audioPlayer = audioPlayer;
		}
//		
//		public void setPlaying(boolean playing){
//			lock.lock();
//			b_isPlaying = playing;
//			lock.unlock();
//		}
		
		
		public void play(String audio){
			//this.audio = audio;
			//this.loop = loop;
			Log.e(TAG, "play.. audio:"+audio);
			//setPlaying(true);
			if (audio == null || audio.isEmpty())
				return;
			Command c = new Command(Command.COMMAND_START, false, audio);
			cmdQueue.add(c);
		}
		public void release(){
			Command c = new Command(Command.COMMAND_RELEASE, false, null);
			cmdQueue.add(c);
		}
		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			while(!b_exits){
				Command c = null;
				try {
					c = cmdQueue.take();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				if (c == null)
					continue;
				Log.e(TAG, "entry..");
				if (c.command == Command.COMMAND_START){
					playAudioMayFade(c);
				}else if (c.command == Command.COMMAND_RELEASE){
					b_exits = true;
				}
			}
			Log.e(TAG, "audio thread exist ok");
		}
		
	}
}
